home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October : Technology Seed / ATS Oct. '97.toast / Navigation Services SDK 1.0a6 / Examples / Sampler / Sampler ƒ / menus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-31  |  22.2 KB  |  874 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        menus.c
  3.  
  4.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment AppSeg
  9.  
  10. #ifndef __SCRAP__
  11. #include <Scrap.h>
  12. #endif
  13.  
  14. #ifndef __DEVICES__
  15. #include <Devices.h>
  16. #endif
  17.  
  18. #ifndef __TOOLUTILS__
  19. #include <ToolUtils.h>
  20. #endif
  21.  
  22.  
  23. #ifndef Common_Defs
  24. #include "Common.h"
  25. #endif
  26.  
  27. extern Document* gDocumentList[kMaxDocumentCount];
  28. extern short    gDocumentCount;
  29. extern short    gCanUndoDrag;
  30. extern short    gQuit, gQuitting;
  31. extern Boolean    gNavServicesExists;
  32.  
  33. // prototypes:
  34. void SetItemEnable( MenuHandle theMenu, short theItem, short enable );
  35. short DoPaste( );
  36. void DoAbout( );
  37. void DoSelectDictionary( );
  38. void DoSelectDirectory( );
  39. void DoSelectObject( );
  40. void DoSelectVolume( );
  41. void DoCreateFolder( );
  42. void DoCustomOpen( );
  43.  
  44. // for customization:
  45. pascal void myCustomEventProc( NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD);
  46. void HandleCustomMouseDown( NavCBRecPtr callBackParms );
  47. void HandleCommandPopup( ControlHandle thePopup, NavCBRecPtr callBackParms );
  48.  
  49.  
  50. // custom dialog item:
  51. #define kControlListID    132
  52. #define kPopupCommand     1
  53.  
  54. // the requested dimensions for our customization area:
  55. #define kCustomWidth    100
  56. #define kCustomHeight    40
  57.                 
  58. // customization globals:
  59. Handle         gDitlList;
  60. MenuHandle     gPopupMenu;
  61. short         gLastTryWidth;
  62. short         gLastTryHeight;
  63.  
  64.                         
  65. // *****************************************************************************
  66. // *
  67. // *    SetItemEnable()
  68. // *
  69. // *****************************************************************************
  70. void SetItemEnable(MenuHandle theMenu, short theItem, short enable)
  71. {
  72.     if (enable)
  73.         EnableItem(theMenu,theItem);
  74.     else
  75.         DisableItem(theMenu,theItem);
  76. }
  77.  
  78.  
  79. // *****************************************************************************
  80. // *
  81. // *    AdjustMenus()
  82. // *
  83. // *****************************************************************************
  84. void AdjustMenus()
  85. {    
  86.     MenuHandle    theMenu;
  87.     Document*    theDocument;
  88.     short        teSelection = 0;
  89.     Str255        theStr;
  90.  
  91.     theDocument = IsDocumentWindow((WindowPtr)FrontWindow());
  92.     
  93.     if (theDocument->theTE != NULL)
  94.         teSelection = (theDocument) && ((**(theDocument->theTE)).selStart != (**(theDocument->theTE)).selEnd);
  95.  
  96.     theMenu = GetMenuHandle(idFileMenu);
  97.  
  98.     SetItemEnable(theMenu,NewItem,gDocumentCount < kMaxDocumentCount);
  99.     SetItemEnable(theMenu,OpenItem,gDocumentCount < kMaxDocumentCount);
  100.  
  101.     SetItemEnable(theMenu,CloseItem,theDocument != 0L);
  102.     SetItemEnable(theMenu,SaveItem,(theDocument) && (theDocument->dirty));
  103.     SetItemEnable(theMenu,RevertItem,(theDocument) && (theDocument->dirty) && (theDocument->fRefNum));
  104.     SetItemEnable(theMenu,SaveACopyItem,theDocument != 0L);
  105.     SetItemEnable(theMenu,DictionaryItem,gNavServicesExists);
  106.  
  107.     theMenu = GetMenuHandle(idEditMenu);
  108.  
  109.     GetIndString(theStr,MenuStringsID,gCanUndoDrag);
  110.     SetMenuItemText(theMenu,iUndo,theStr);
  111.     SetItemEnable(theMenu,iUndo,gCanUndoDrag != slCantUndo);
  112.  
  113.     SetItemEnable(theMenu,iCut,teSelection);
  114.     SetItemEnable(theMenu,iCopy,teSelection);
  115.     SetItemEnable(theMenu,iPaste,theDocument != 0L);
  116.     SetItemEnable(theMenu,iClear,teSelection);
  117.     SetItemEnable(theMenu,iSelectAll,theDocument != 0L);
  118.  
  119.     theMenu = GetMenuHandle(idUtilsMenu);
  120.     SetItemEnable(theMenu,iSelectDir,gNavServicesExists);
  121.     SetItemEnable(theMenu,iSelectVol,gNavServicesExists);
  122.     SetItemEnable(theMenu,iCreateFolder,gNavServicesExists);
  123.     SetItemEnable(theMenu,iCustomOpen,gNavServicesExists);
  124. }
  125.  
  126.  
  127. // *****************************************************************************
  128. // *
  129. // *    DoPaste()
  130. // *
  131. // *****************************************************************************
  132. short DoPaste()
  133. {    
  134.     long    size, offset;
  135.     Handle    theData;
  136.  
  137.     size = GetScrap(0L,'UPRC',&offset);
  138.  
  139.     if (size <= 0)
  140.         return(0);
  141.  
  142.     theData = NewHandle(size);
  143.     GetScrap(theData,'UPRC',&offset);
  144.  
  145.     HLock(theData);
  146.     PutScrap(size,'test',*theData);
  147.  
  148.     HUnlock(theData);
  149.     DisposeHandle(theData);
  150.  
  151.     return noErr;
  152. }
  153.  
  154.  
  155. // *****************************************************************************
  156. // *
  157. // *    DoSelectDictionary()
  158. // *    
  159. // *****************************************************************************
  160. void DoSelectDictionary()
  161. {    
  162.     NavReplyRecord        theReply;
  163.     NavDialogOptions    dialogOptions;
  164.     OSErr                theErr = noErr;
  165.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  166.     NavTypeListHandle    openList = NULL;
  167.     
  168.     // use the default location for the dialog:
  169.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  170.  
  171.     GetIndString(dialogOptions.message,rAppStringsID,sChooseFile);
  172.  
  173.     dialogOptions.preferenceKey = kSelectFilePrefKey;
  174.     
  175.     openList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  176.     if ((openList != NULL)&&(ResError() == noErr))
  177.         HLock((Handle)openList);
  178.         
  179.     theErr = NavChooseFile(    NULL,
  180.                             &theReply,
  181.                             &dialogOptions,
  182.                             eventUPP,
  183.                             NULL,
  184.                             NULL,
  185.                             openList,
  186.                             (NavCallBackUserData)&gDocumentList);
  187.     
  188.     DisposeRoutineDescriptor(eventUPP);
  189.     
  190.     if ((theReply.validRecord)&&(theErr == noErr))
  191.         {
  192.         // grab the target FSSpec from the AEDesc:    
  193.         FSSpec    finalFSSpec;    
  194.         AEDesc     resultDesc;
  195.  
  196.         theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc);
  197.         if (theErr == noErr)
  198.             {
  199.             BlockMove(*resultDesc.dataHandle,(void*)&finalFSSpec,sizeof(FSSpec));    
  200.             // 'finalFSSpec' is the chosen file…
  201.             }
  202.             
  203.         theErr = NavDisposeReply(&theReply);
  204.         }
  205.     
  206.     HUnlock((Handle)openList);
  207.     DisposeHandle((Handle)openList);
  208. }
  209.  
  210.  
  211. // *****************************************************************************
  212. // *
  213. // *    DoSelectDirectory()
  214. // *    
  215. // *****************************************************************************
  216. void DoSelectDirectory()
  217. {    
  218.     NavReplyRecord        theReply;
  219.     NavDialogOptions    dialogOptions;
  220.     OSErr                theErr = noErr;
  221.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  222.     
  223.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  224.     
  225.     GetIndString(dialogOptions.message,rAppStringsID,sChooseFolder);
  226.     
  227.     dialogOptions.preferenceKey = kSelectFolderPrefKey;
  228.     
  229.     theErr = NavChooseFolder(    NULL,
  230.                                 &theReply,
  231.                                 &dialogOptions,
  232.                                 eventUPP,
  233.                                 NULL,
  234.                                 (NavCallBackUserData)&gDocumentList);
  235.     
  236.     DisposeRoutineDescriptor(eventUPP);
  237.  
  238.     if ((theReply.validRecord)&&(theErr == noErr))
  239.         {
  240.         // grab the target FSSpec from the AEDesc:    
  241.         FSSpec    finalFSSpec;    
  242.         AEDesc     resultDesc;
  243.  
  244.         theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc);
  245.         if (theErr == noErr)
  246.             {
  247.             BlockMove(*resultDesc.dataHandle,(void*)&finalFSSpec,sizeof(FSSpec));    
  248.             // 'finalFSSpec' is the selected directory…
  249.             }
  250.         
  251.         theErr = NavDisposeReply(&theReply);
  252.         }
  253. }
  254.  
  255.  
  256. // *****************************************************************************
  257. // *
  258. // *    DoSelectObject()
  259. // *    
  260. // *****************************************************************************
  261. void DoSelectObject()
  262. {    
  263.     NavReplyRecord        theReply;
  264.     NavDialogOptions    dialogOptions;
  265.     OSErr                theErr = noErr;
  266.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  267.     
  268.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  269.     
  270.     GetIndString(dialogOptions.message,rAppStringsID,sChooseObject);
  271.     
  272.     dialogOptions.preferenceKey = kSelectObjectPrefKey;
  273.     
  274.     theErr = NavChooseObject(    NULL,
  275.                                 &theReply,
  276.                                 &dialogOptions,
  277.                                 eventUPP,
  278.                                 NULL,
  279.                                 (NavCallBackUserData)&gDocumentList);
  280.     
  281.     DisposeRoutineDescriptor(eventUPP);
  282.  
  283.     if ((theReply.validRecord)&&(theErr == noErr))
  284.         {
  285.         // grab the target FSSpec from the AEDesc:    
  286.         FSSpec    finalFSSpec;    
  287.         AEDesc     resultDesc;
  288.  
  289.         theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc);
  290.         if (theErr == noErr)
  291.             {
  292.             BlockMove(*resultDesc.dataHandle,(void*)&finalFSSpec,sizeof(FSSpec));    
  293.             // 'finalFSSpec' is the selected directory…
  294.             }
  295.         
  296.         theErr = NavDisposeReply(&theReply);
  297.         }
  298. }
  299.  
  300.  
  301.  
  302. // *****************************************************************************
  303. // *
  304. // *    DoSelectVolume()
  305. // *    
  306. // *****************************************************************************
  307. void DoSelectVolume()
  308. {    
  309.     NavReplyRecord        theReply;
  310.     NavDialogOptions    dialogOptions;
  311.     OSErr                theErr = noErr;
  312.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  313.     
  314.     // use the default location for the dialog:
  315.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  316.     
  317.     GetIndString(dialogOptions.message,rAppStringsID,sChooseVolume);
  318.  
  319.     dialogOptions.preferenceKey = kSelectVolumePrefKey;
  320.     
  321.     theErr = NavChooseVolume(    NULL,
  322.                                 &theReply,
  323.                                 &dialogOptions,
  324.                                 eventUPP,
  325.                                 NULL,
  326.                                 (NavCallBackUserData)&gDocumentList);
  327.     if ((theReply.validRecord)&&(theErr == noErr))
  328.         {
  329.         // grab the target FSSpec from the AEDesc:    
  330.         FSSpec    finalFSSpec;    
  331.         AEDesc     resultDesc;
  332.  
  333.         // there is only one selection here we get only the first AEDesc:
  334.         theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc);
  335.         if (theErr == noErr)
  336.             {
  337.             BlockMove(*resultDesc.dataHandle,(void*)&finalFSSpec,sizeof(FSSpec));
  338.             // 'finalFSSpec' is the chosen volume…
  339.             }
  340.         
  341.         theErr = NavDisposeReply(&theReply);
  342.         }
  343.         
  344.     DisposeRoutineDescriptor(eventUPP);
  345. }
  346.  
  347.  
  348. // *****************************************************************************
  349. // *
  350. // *    DoCreateFolder()
  351. // *    
  352. // *****************************************************************************
  353. void DoCreateFolder()
  354. {    
  355.     NavReplyRecord        theReply;
  356.     NavDialogOptions    dialogOptions;
  357.     OSErr                theErr = noErr;
  358.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  359.     
  360.     // use the default location for the dialog:
  361.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  362.     
  363.     GetIndString(dialogOptions.message,rAppStringsID,sCreateFolder);
  364.  
  365.     dialogOptions.preferenceKey = kNewFolderPrefKey;
  366.     
  367.     theErr = NavNewFolder(    NULL,
  368.                             &theReply,
  369.                             &dialogOptions,
  370.                             eventUPP, 
  371.                             (NavCallBackUserData)&gDocumentList);
  372.     if (theReply.validRecord)
  373.         {
  374.         // grab the target FSSpec from the AEDesc:    
  375.         FSSpec    finalFSSpec;    
  376.         AEDesc     resultDesc;
  377.  
  378.         // there is only one selection here so we get the first AEDesc:
  379.         theErr = AECoerceDesc(&(theReply.selection),typeFSS,&resultDesc);
  380.         if (theErr == noErr)
  381.             {
  382.             BlockMove(*resultDesc.dataHandle,(void*)&finalFSSpec,sizeof(FSSpec));
  383.             // 'finalFSSpec' is the newly created folder…
  384.             }
  385.  
  386.         theErr = NavDisposeReply(&theReply);
  387.         }
  388. }
  389.  
  390.  
  391. // *****************************************************************************
  392. // *
  393. // *    HandleCommandPopup()
  394. // *    
  395. // *****************************************************************************
  396. void HandleCommandPopup(ControlHandle thePopup, NavCBRecPtr callBackParms)
  397. {
  398.     OSErr     theErr = noErr;
  399.     short     selection = 0;
  400.     
  401.     selection = GetControlValue(thePopup)-1;
  402.     switch (selection)
  403.         {                                
  404.         case kNavCtlShowDesktop:
  405.         case kNavCtlScrollHome:
  406.         case kNavCtlScrollEnd:
  407.         case kNavCtlPageUp:
  408.         case kNavCtlPageDown:
  409.             theErr = NavCustomControl(callBackParms->context,selection,NULL);
  410.             break;
  411.         
  412.         case kNavCtlShowSelection:
  413.             theErr = NavCustomControl(callBackParms->context,kNavCtlShowSelection,NULL);
  414.             break;
  415.         
  416.         case kNavCtlOpenSelection:
  417.             {
  418.             AEDesc itemToOpen;
  419.             theErr = NavCustomControl(callBackParms->context,kNavCtlOpenSelection,&itemToOpen);
  420.             if (itemToOpen.descriptorType == typeFSS)
  421.                 {    
  422.                 // you may open the file as described by 'itemToOpen', or do whatever you want with it:
  423.                 AEDisposeDesc(&itemToOpen);
  424.                 }
  425.             break;
  426.             }
  427.             
  428.         case kNavCtlCancel:
  429.             theErr = NavCustomControl(callBackParms->context,kNavCtlCancel,NULL);
  430.             break;
  431.     
  432.         case kNavCtlAccept:
  433.             theErr = NavCustomControl(callBackParms->context,kNavCtlAccept,NULL);
  434.             break;
  435.         }
  436. }
  437.  
  438.  
  439. void HandleCustomMouseDown(NavCBRecPtr callBackParms)
  440. {
  441.     OSErr            theErr = noErr;
  442.     ControlHandle    whichControl;                
  443.     Point             where = callBackParms->eventData.event->where;    
  444.     short            theItem = 0;    
  445.     UInt16             firstItem = 0;
  446.     short            realItem = 0;
  447.     short            partCode = 0;
  448.         
  449.     GlobalToLocal(&where);
  450.     theItem = FindDialogItem(callBackParms->window,where);    // get the item number of the control
  451.     partCode = FindControl(where,callBackParms->window,&whichControl);    // get the control itself
  452.     
  453.     // ask NavServices for the first custom control's ID:
  454.     if (callBackParms->context != 0)    // always check to see if the context is correct
  455.         {
  456.         theErr = NavCustomControl(callBackParms->context,kNavCtlGetFirstControlID,&firstItem);    
  457.         realItem = theItem - firstItem + 1;        // map it to our DITL constants:    
  458.         }
  459.                 
  460.     if (realItem == kPopupCommand)
  461.         HandleCommandPopup(whichControl,callBackParms);
  462. }                    
  463.  
  464.  
  465. // *****************************************************************************
  466. // *
  467. // *    myEventProc()    
  468. // *
  469. // *****************************************************************************
  470. pascal void myCustomEventProc(    NavEventCallbackMessage callBackSelector, 
  471.                                 NavCBRecPtr callBackParms, 
  472.                                 NavCallBackUserData callBackUD)
  473. {
  474.     OSErr        theErr = noErr;
  475.     WindowPtr    pWindow = NULL;
  476.     Document**    docList;
  477.     Document*    theDoc = NULL;
  478.     short         index = 0;
  479.  
  480.     if (callBackUD != 0)
  481.         switch (callBackSelector)
  482.             {
  483.             case kNavCBEvent:
  484.                 {
  485.                 docList = (Document**)callBackUD;
  486.                 if (docList != NULL)
  487.                     switch (callBackParms->eventData.event->what)
  488.                         {
  489.                         case mouseDown:
  490.                             HandleCustomMouseDown(callBackParms);
  491.                             break;
  492.                         
  493.                         case updateEvt:
  494.                             pWindow = (WindowPtr)callBackParms->eventData.event->message;
  495.                             theDoc = docList[index];
  496.                             if (theDoc != NULL)
  497.                                 {
  498.                                 while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  499.                                     {
  500.                                     index++;
  501.                                     theDoc = docList[index];
  502.                                     }
  503.                                 theDoc = docList[index];
  504.                                 if (theDoc != NULL)
  505.                                     UpdateWindow(theDoc);
  506.                                 }
  507.                             break;
  508.  
  509.                         default:
  510.                             break;
  511.                         }
  512.                 break;
  513.                 }
  514.     
  515.             case kNavCBCustomize:
  516.                 {                                
  517.                 // here are the desired dimensions for our custom area:
  518.                 short neededWidth = callBackParms->customRect.left + kCustomWidth;
  519.                 short neededHeight = callBackParms->customRect.top + kCustomHeight;
  520.                 
  521.                 // check to see if this is the first round of negotiations:
  522.                 if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))
  523.                     {
  524.                     // it is, so tell NavServices what dimensions we want:
  525.                     callBackParms->customRect.right = neededWidth;
  526.                     callBackParms->customRect.bottom = neededHeight;
  527.                     }
  528.                 else
  529.                     {
  530.                     // we are in the middle of negotiating:
  531.                     if (gLastTryWidth != callBackParms->customRect.right)
  532.                         if (callBackParms->customRect.right < neededWidth)    // is NavServices width too small for us?
  533.                             callBackParms->customRect.right = neededWidth;
  534.  
  535.                     if (gLastTryHeight != callBackParms->customRect.bottom)    // is NavServices height too small for us?
  536.                         if (callBackParms->customRect.bottom < neededHeight)
  537.                             callBackParms->customRect.bottom = neededHeight;
  538.                     }
  539.                 
  540.                 // remember our last size so the next time we can re-negotiate:
  541.                 gLastTryWidth = callBackParms->customRect.right;
  542.                 gLastTryHeight = callBackParms->customRect.bottom;    
  543.                 break;
  544.                 }
  545.                 
  546.             case kNavCBStart:
  547.                 {
  548.                 short    itemType;
  549.                 Rect    itemRect;
  550.                 Handle    itemH;
  551.                 UInt16     firstItem = 0;    
  552.                 short    realItem = 0;
  553.                 
  554.                 // add the rest of the custom controls via the DITL resource list:
  555.                 gDitlList = GetResource('DITL',kControlListID);
  556.                 if ((gDitlList != NULL)&&(ResError() == noErr))
  557.                     if ((theErr = NavCustomControl(callBackParms->context,kNavCtlAddControlList,gDitlList)) == noErr)
  558.                         {
  559.                         theErr = NavCustomControl(callBackParms->context,kNavCtlGetFirstControlID,&firstItem);    // ask NavServices for our first control ID
  560.                                 
  561.                         // set the command popup selection:
  562.                         realItem = firstItem + kPopupCommand;
  563.                         GetDialogItem(callBackParms->window,realItem,&itemType,&itemH,&itemRect);
  564.                         SetControlValue((ControlHandle)itemH,1);
  565.                         }
  566.                     
  567.                 // the dialog is starting up, let's override the default popup menu selection:
  568.                 UInt16 itemToSelect = kAllReadableFiles;
  569.                 theErr = NavCustomControl(callBackParms->context,kNavCtlSelectAllType,&itemToSelect);
  570.                 break;
  571.                 }
  572.                 
  573.             case kNavCBTerminate:
  574.                 // release our appended popup menu:
  575.                 if (gDitlList)
  576.                     ReleaseResource(gDitlList);        
  577.                 if (gPopupMenu)
  578.                     DisposeMenu(gPopupMenu);        
  579.                 break;
  580.             }
  581. }
  582.  
  583.  
  584. // *****************************************************************************
  585. // *
  586. // *    DoCustomOpen()
  587. // *    
  588. // *****************************************************************************
  589. void DoCustomOpen()
  590. {    
  591.     NavReplyRecord        theReply;
  592.     NavDialogOptions    dialogOptions;
  593.     OSErr                theErr = noErr;
  594.     NavTypeListHandle    typeList = NULL;
  595.     long                count = 0;
  596.     NavEventUPP            eventUPP = NewNavEventProc(myCustomEventProc);
  597.     
  598.     // default behavior for browser and dialog:
  599.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  600.  
  601.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  602.     
  603.     typeList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  604.     if ((typeList != NULL)&&(ResError() == noErr))
  605.         HLock((Handle)typeList);
  606.  
  607.     theErr = NavGetFile(NULL,    // use system's default location
  608.                         &theReply,
  609.                         &dialogOptions,
  610.                         eventUPP,
  611.                         NULL,    // no custom previews
  612.                         NULL,
  613.                         typeList,
  614.                         (NavCallBackUserData)&gDocumentList);
  615.  
  616.     DisposeRoutineDescriptor(eventUPP);
  617.  
  618.     if (theReply.validRecord && theErr == noErr)
  619.         {
  620.         // since we allow for multiple objects to be returned,
  621.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  622.         FSSpec    finalFSSpec;    
  623.         AEDesc     resultDesc;
  624.         FInfo    fileInfo;
  625.  
  626.         // we are ready to open the document(s), grab information about each file for opening:
  627.         theErr = AECountItems(&(theReply.selection),&count);
  628.         for (long index=1;index<=count;index++)
  629.             {
  630.             resultDesc.dataHandle = 0L;
  631.             theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc);
  632.             if (theErr == noErr)
  633.                 {
  634.                 BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  635.             
  636.                 // decide if the doc we are opening is a 'PICT' or 'TEXT':
  637.                 theErr = FSpGetFInfo(&finalFSSpec,&fileInfo);
  638.                 if (theErr == noErr)
  639.                     {
  640.                     if (fileInfo.fdType == kFileType)
  641.                         (void)DoOpenFile(&finalFSSpec,false);
  642.                     else
  643.                         if (fileInfo.fdType == kFileTypePICT)
  644.                             (void)DoOpenFile(&finalFSSpec,true);
  645.                         else
  646.                             {
  647.                             // error:
  648.                             // if we got this far, the document is a type we can't open and
  649.                             // (most likely) built-in translation was turned off.
  650.                             // You can alert the user that this returned selection or file spec
  651.                             // needs translation.
  652.                             }
  653.                     }
  654.                 theErr = AEDisposeDesc(&resultDesc);
  655.                 }
  656.             }
  657.         
  658.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  659.         }
  660.  
  661.     if (typeList != NULL)
  662.         {
  663.         HUnlock((Handle)typeList);
  664.         ReleaseResource((Handle)typeList);
  665.         }
  666.  
  667. }
  668.  
  669.  
  670. // *****************************************************************************
  671. // *
  672. // *    DoAbout()
  673. // *    
  674. // *****************************************************************************
  675. void DoAbout()
  676. {
  677.     GrafPtr        savePort;
  678.     DialogPtr    aboutDialog;
  679.     short        itemHit = 0;
  680.     Handle        itemH;
  681.     short        itemType;
  682.     Rect        itemRect;
  683.     
  684.     SetCursor(&qd.arrow);
  685.     aboutDialog = GetNewDialog(rAboutID,nil,(WindowRef)-1);
  686.     
  687.     GetPort(&savePort);
  688.  
  689.     SetPort((GrafPtr)aboutDialog);
  690.  
  691.     AdornButton(aboutDialog,dOK);
  692.  
  693.     GetDialogItem(aboutDialog,iIconSuite,&itemType,&itemH,&itemRect);
  694.     DrawIconSuite(rIconSuite,itemRect);
  695.                     
  696.     do ModalDialog(nil,&itemHit);
  697.  
  698.     while(itemHit != dOK);
  699.     
  700.     SetPort(savePort);
  701.     DisposeDialog(aboutDialog);
  702. }
  703.  
  704.  
  705. // *****************************************************************************
  706. // *
  707. // *    DoMenuCommand()
  708. // *
  709. // *****************************************************************************
  710. void DoMenuCommand(long select)
  711. {    
  712.     short        theMenuID, theItem;
  713.     MenuHandle    theMenu;
  714.     Str255        theName;
  715.     WindowPtr    theWindow;
  716.     Document*    theDocument = nil;
  717.     OSStatus    theErr = noErr;
  718.  
  719.     theDocument = IsDocumentWindow(theWindow = (WindowPtr)FrontWindow());
  720.  
  721.     theItem   = LoWord(select);
  722.     theMenuID = HiWord(select);
  723.     theMenu   = GetMenuHandle(theMenuID);
  724.     switch(theMenuID)
  725.         {
  726.         case idAppleMenu:
  727.             switch(theItem)
  728.                 {
  729.                 case AboutItem:
  730.                     DoAbout();
  731.                     break;
  732.                 default:
  733.                     GetMenuItemText(GetMenuHandle(idAppleMenu),theItem,(unsigned char*)&theName);
  734.                     OpenDeskAcc(theName);
  735.                 }
  736.             break;
  737.             
  738.         case idFileMenu:
  739.             switch(theItem)
  740.                 {
  741.                 case NewItem:
  742.                     DoNewDocument(false);
  743.                     AdjustMenus();
  744.                     break;
  745.                     
  746.                 case OpenItem:
  747.                     if (gNavServicesExists)
  748.                         (void)DoOpenDocument();
  749.                     else    
  750.                         (void)DoOpenDocumentTheOldWay();
  751.                     AdjustMenus();        
  752.                     break;
  753.                     
  754.                 case CloseItem:
  755.                     if (theDocument)
  756.                         {
  757.                         CloseDocument(theDocument,false);
  758.                         AdjustMenus();
  759.                         DrawMenuBar();
  760.                         }
  761.                     break;
  762.                     
  763.                 case SaveItem:
  764.                     if (theDocument)
  765.                         DoSaveDocument(theDocument);
  766.                     break;
  767.                 
  768.                 case SaveACopyItem:
  769.                     if (theDocument)
  770.                         {
  771.                         if (gNavServicesExists)
  772.                             (void)SaveACopyDocument(theDocument);
  773.                         else
  774.                             (void)SaveACopyDocumentTheOldWay(theDocument);
  775.                         }
  776.                     break;
  777.     
  778.                 case RevertItem:
  779.                     DisableUndoDrag();
  780.                     if (theDocument)
  781.                         {
  782.                         if (gNavServicesExists)
  783.                             DoRevertDocument(theDocument);
  784.                         else
  785.                             DoRevertDocumentTheOldWay(theDocument);
  786.                         }
  787.                     break;
  788.  
  789.                 case DictionaryItem:
  790.                     DoSelectDictionary();
  791.                     break;
  792.  
  793.                 case QuitItem:
  794.                     gQuitting = true;
  795.                     while ((gQuitting) && (theDocument = IsDocumentWindow((WindowPtr)FrontWindow())))
  796.                         CloseDocument(theDocument,true);
  797.                     if (gQuitting)
  798.                         gQuit = true;
  799.                     break;
  800.                 }
  801.             break;
  802.             
  803.         case idEditMenu:
  804.             switch(theItem)
  805.                 {
  806.                 case iUndo:
  807.                     DoUndoDrag();
  808.                     break;
  809.                     
  810.                 case iCut:
  811.                     if ((theDocument)&&(theDocument->theTE != NULL))
  812.                         {
  813.                         DisableUndoDrag();
  814.                         myTECut(theDocument->theTE);
  815.                         }
  816.                     break;
  817.                     
  818.                 case iCopy:
  819.                     if (theDocument)
  820.                         TECopy(theDocument->theTE);
  821.                     break;
  822.                     
  823.                 case iPaste:
  824.                     if ((theDocument)&&(theDocument->theTE != NULL))
  825.                         if (!DoPaste())
  826.                             {
  827.                             DisableUndoDrag();
  828.                             myTEPaste(theDocument->theTE,0L,0L);
  829.                             }
  830.                     break;
  831.                     
  832.                 case iClear:
  833.                     if ((theDocument)&&(theDocument->theTE != NULL))
  834.                         {
  835.                         DisableUndoDrag();
  836.                         TEDelete(theDocument->theTE);
  837.                         }
  838.                     break;
  839.                     
  840.                 case iSelectAll:
  841.                     if ((theDocument)&&(theDocument->theTE != NULL))
  842.                         DoSelectAllDocument(theDocument);
  843.                     break;
  844.                 }
  845.  
  846.             case idUtilsMenu:
  847.                 switch (theItem)
  848.                     {
  849.                     case iSelectDir:
  850.                         DoSelectDirectory();
  851.                         break;
  852.                     case iSelectVol:
  853.                         DoSelectVolume();
  854.                         break;
  855.                     case iSelectObject:
  856.                         DoSelectObject();
  857.                         break;
  858.                     case iCreateFolder:
  859.                         DoCreateFolder();
  860.                         break;
  861.                     case iCustomOpen:
  862.                         DoCustomOpen();
  863.                         break;
  864.                     }
  865.         }        
  866.  
  867.     if (theDocument = IsDocumentWindow((WindowPtr)FrontWindow()))
  868.         if (theDocument->theTE != NULL)
  869.             TEGetHiliteRgn(theDocument->hiliteRgn,theDocument->theTE);
  870.  
  871.     HiliteMenu(0);
  872. }
  873.  
  874.